﻿using Abp;
using Abp.Application.Services.Dto;
using Abp.Auditing;
using Abp.Authorization;
using Abp.Domain.Entities;
using Abp.Domain.Repositories;
using Abp.Events.Bus;
using Abp.Linq;
using Abp.Localization;
using Abp.MultiTenancy;
using Abp.Runtime.Session;
using AbpProjectTemplate.Application.Filters;
using AbpProjectTemplate.Domain.Users;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AbpProjectTemplate.Extensions;
using AbpProjectTemplate.Utilities.Theading;

namespace AbpProjectTemplate.Application
{
    [DisableAuditing]
    public abstract class ApplicationService : Abp.Application.Services.ApplicationService, IApplicationService
    {
        public IEventBus EventBus { get; set; }
        public IUserCache UserCache { get; set; }
        public ITenantCache TenantCache { get; set; }
        public IAsyncQueryableExecuter AsyncQueryableExecuter { get; set; }
        /// <summary>
        /// 并发控制器
        /// </summary>
        public SemaphoreSlimManager SemaphoreSlimManager { get; set; }
        protected ApplicationService()
        {
            this.LocalizationSourceName = AppConsts.LocalizationSourceName;

            this.EventBus = NullEventBus.Instance;
            this.AsyncQueryableExecuter = NullAsyncQueryableExecuter.Instance;
        }
        /// <summary>
        /// 当前登录用户ID
        /// </summary>
        protected long CurrentUserId
        {
            get
            {
                if (!this.AbpSession.UserId.HasValue)
                    throw new AbpAuthorizationException(this.LocalizationManager.GetString(AbpConsts.LocalizationSourceName, "CurrentUserDidNotLoginToTheApplication"));
                return this.AbpSession.UserId.Value;
            }
        }
        protected virtual void CheckPermission(string permissionName)
        {
            if (!string.IsNullOrEmpty(permissionName))
            {
                this.PermissionChecker.Authorize(permissionName);
            }
        }
        /// <summary>
        /// 获取当前登录用户信息
        /// </summary>
        protected virtual async Task<TenantCacheItem> GetCurrentTenantAsync()
        {
            var item = this.TenantCache.GetOrNull(this.AbpSession.GetTenantId());
            if (item == null)
            {
                throw new AppUserFriendlyException($"不存在的租户：{this.AbpSession.GetTenantId()}。");
            }
            return await Task.FromResult(item);
        }
        /// <summary>
        /// 获取当前登录用户信息
        /// </summary>
        protected virtual async Task<User> GetCurrentUserAsync()
        {
            var item = await this.UserCache.GetAsync(this.CurrentUserId);
            if (item == null)
            {
                throw new AppUserFriendlyException($"不存在的用户：{this.CurrentUserId}。");
            }
            return item;
        }
        /// <summary>
        /// 创建分页数据
        /// </summary>
        protected virtual async Task<PagedResultDto<T>> CreatePagedResultAsync<T>(IQueryable<T> query, PagedRequestFilter filter)
        {
            var totalCcount = await this.AsyncQueryableExecuter.CountAsync(query);
            var items = await query.PageAndSortBy(filter).ToListAsync();

            return new PagedResultDto<T>(totalCcount, items);
        }
        /// <summary>
        /// 创建分页数据创建并返回指定的Result对像
        /// </summary>
        protected virtual async Task<TResult> CreatePagedResultAsync<T, TResult>(IQueryable<T> query, PagedRequestFilter filter)
            where TResult : PagedResultDto<T>, new()
        {
            var totalCcount = await query.CountAsync();
            var items = await query.PageAndSortBy(filter).ToListAsync();

            var result = new TResult
            {
                Items = items,
                TotalCount = totalCcount
            };
            return result;
        }
        /// <summary>
        /// 创建分页数据返回结果，并自动从TEntity映射到TEntityDto（先返回数据再映射）
        /// </summary>
        protected virtual async Task<TResult> CreatePagedResultMapAfterAsync<T, TDto, TResult>(
            IQueryable<T> query,
            PagedRequestFilter filter)
            where TResult : PagedResultDto<TDto>, new()
        {
            var totalCcount = await query.CountAsync();
            var items = await query.PageAndSortBy(filter).ToListAsync();

            var result = new TResult { Items = this.ObjectMapper.Map<List<TDto>>(items), TotalCount = totalCcount };
            return result;
        }

        /// <summary>
        /// 创建分页数据（先返回所有数据再映射）
        /// </summary>
        protected virtual async Task<PagedResultDto<TDto>> CreatePagedResultMapAfterAsync<T, TDto>(
            IQueryable<T> query,
            PagedRequestFilter filter)
        {
            return await this.CreatePagedResultMapAfterAsync<T, TDto, PagedResultDto<TDto>>(query, filter);
        }
    }

    public abstract class ApplicationService<TEntity, TKey> : ApplicationService
        where TEntity : Entity<TKey>
    {
        protected readonly IRepository<TEntity, TKey> Repository;

        public ApplicationService(IRepository<TEntity, TKey> repository)
        {
            this.Repository = repository;
        }
        /// <summary>
        /// id获取实体数据 如果不存在则抛出异常
        /// </summary>
        protected virtual Task<TEntity> GetEntityByIdAsync(TKey id)
        {
            return this.Repository.GetAsync(id);
        }
    }

    public abstract class ApplicationService<TEntity> : ApplicationService<TEntity, int>
        where TEntity : Entity<int>
    {
        public ApplicationService(IRepository<TEntity, int> currentRepository) : base(currentRepository)
        {

        }
    }
}

